/* 

JSON对象中的stringify（）方法用于将JavaScript对象序列化为JSON字符串。在序列化时，包装对象（String、Number和Boolean）会自动转为对应的原始值，
函数和不可枚举的属性都将被忽略，并且非数组对象的属性不能保证以特定顺序出现在序列化后的字符串中，stringify（）有3个参数：
（1）第一个参数（o）是要转换成JSON字符串的原始值、数组或对象。
（2）第二个参数（filter）是可选的过滤器，用于替换或移除一些值，可以是函数或数组，下面会详解。
    stringify()方法的第二个参数是过滤器，当过滤器是一个函数时，它能接收两个参数：一个键和一个值，
    如果函数返回值是undefined，那么相应的键在序列化时将会被跳过。过滤器会遍历JSON数据中的数组，
    在函数中也能操纵它们的键和值，但返回undefined，不会被忽略，而是被替换为null。

    当过滤器是一个数组时，由数组来指定需要序列化的属性名（即键）。例如指定属性名name和age，最终返回的结果将会忽略colors属性
    （只在本层属性有效）
（3）第三个参数（indent）用于控制结果中的缩进和空白符，可以输入数字或字符串。

*/

// 一个参数的版本：
function myStringify(obj) {
    const arr = [];

    // 递归格式化函数
    const format = function (val) {
        // 判断val是否为对象，如果是对象，递归实现格式化
        if (typeof val == 'object' && val !== null) return myStringify(val);

        // 若不是对象，判断是否为字符串，若为字符串成，val用""包括，若为数字，不做处理
        // return /^(string)$/.test(typeof val) ? `"${val}"` : val;
        return typeof val === "string" ? `"${val}"` : val;
    }

    // 递归格式化
    for (const key in obj) {
        // 判断该属性是否可枚举
        if (Object.getOwnPropertyDescriptor(obj, key).enumerable)
            arr.push(`"${key}":${format(obj[key])}`)
    }


    // 把数组变为字符串，并在最外层加上"{}"
    return `{${arr.join(',')}}`
}

// 两个参数版本：
function myStringify(obj) {
    const arr = [];
    const args = arguments;

    // 递归格式化函数
    const format = function (val) {
        // 判断val是否为对象，如果是对象，递归实现格式化
        if (typeof val == 'object' && val !== null) return myStringify(val);

        // 若不是对象，判断是否为字符串，若为字符串成，val用""包括，若为数字，不做处理
        // return /^(string)$/.test(typeof val) ? `"${val}"` : val;
        return typeof val === "string" ? `"${val}"` : val;
    }

    // 递归格式化
    for (const key in obj) {
        // 判断该属性是否可枚举
        if (Object.getOwnPropertyDescriptor(obj, key).enumerable) {
            if (args.length === 1) {
                arr.push(`"${key}":${format(obj[key])}`)
            } else if (args.length >= 2) {
                const filter = args[1];
                if (typeof filter === 'function') {
                    if (typeof filter(key, obj[key]) != 'undefined') arr.push(`"${key}":${format(obj[key])}`)
                } else if (Array.isArray(filter)) {
                    if (filter.indexOf(key) !== -1) arr.push(`"${key}":${format(obj[key])}`)
                } else {
                    return Error("第二个参数为一个函数或者一个数组")
                }
            }
        }
    }


    // 把数组变为字符串，并在最外层加上"{}"
    return `{${arr.join(',')}}`
}



var myObj = {
    name: "Lily",
    age: 30,
    tel: "132xxxxxxxx",
    address: {
        city: "beijing",
        district: "haidian",
        detail: {
            street: "zhongshanlu",
            house_number: 43
        }
    }
};

var generatedData1 = myStringify(myObj, function (key, value) {
    if (key === "name") return undefined;
    else return value;
})
console.log(generatedData1)
var generatedData2 = JSON.stringify(myObj, function (key, value) {
    if (key === "name") return undefined;
    else return value;
});
console.log(generatedData2)